﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Quaack.Data
{
    public class Bericht
    {

        public int Id
        {
            get { return _id; }
        }

        public DateTime Datum
        {
            get { return _datum; }
        }

        public String Tekst
        {
            get { return _tekst; }
        }

        public Boolean IsVerwijderd
        {
            get { return _isVerwijderd; }
        }

        private int _id;
        private DateTime _datum;
        private int _sender;
        private int? _parentId;
        private String _tekst;
        private Boolean _isVerwijderd;
        private int _verwijderdDoor;

        /// <summary>
        /// Te selecteren kolommen uit de database
        /// </summary>
        public static readonly string Select = "[message].[messid], [message].[messdatetime], [message].[sender], [message].[parentmessid], [message].[message], [message].[removed], [message].[removedby]";

        /// <summary>
        /// Lege constructor verbergen, kan alleen worden uitgevoerd bij
        /// het ophalen van objecten uit de database
        /// </summary>
        private Bericht()
        {
        }

        public Bericht(Profiel eigenaar, string tekst)
            : this(eigenaar, null, tekst)
        {
        }

        private Bericht(Profiel eigenaar, Bericht alsReactieOp, string tekst)
        {
            // Instantie-variables setten
            _datum = DateTime.Now;
            _sender = eigenaar.Id;
            if (alsReactieOp != null)
            {
                _parentId = alsReactieOp.Id;
            }
            _tekst = tekst;

            // Query opbouwen
            string query =
                @"INSERT INTO [message] ([messdatetime], [sender], [parentmessid], [message], [removed]) VALUES
                  (@messdatetime, @sender, @parentmessid, @message, 0)";
            SqlParameter parentmessid = new SqlParameter("parentmessid", System.Data.SqlDbType.Int);
            parentmessid.IsNullable = true;
            if (_parentId == null)
            {
                parentmessid.Value = DBNull.Value;
            }
            else
            {
                parentmessid.Value = _parentId;
            }
            SqlParameter[] parameters = new SqlParameter[] 
            {
                new SqlParameter("messdatetime", _datum),
                new SqlParameter("sender", _sender),
                parentmessid,
                new SqlParameter("message", _tekst),
            };

            // Query runnen
            _id = Provider.Instance.ExecuteInsert(query, parameters);
        }

        public void Update(string nieuweTekst)
        {
            string query = @"UPDATE [message] SET message = @message WHERE messid = @messid";


            SqlParameter[] parameters = new SqlParameter[]
                                            {
                                                new SqlParameter("messid", _id),
                                                new SqlParameter("message", nieuweTekst)
                                            };

            Provider.Instance.Execute(query, parameters);
        }



        /// <summary>
        /// Leest één rij uit een SqlDataReader en zet deze om in een
        /// Bericht-object
        /// </summary>
        /// <param name="reader"></param>
        /// <returns></returns>
        public static Bericht FromReader(SqlDataReader reader)
        {
            // Bericht-object aanmaken
            Bericht bericht = new Bericht();

            // Waardes uit de reader halen
            bericht._id = reader.GetInt32(0);
            bericht._datum = reader.GetDateTime(1);
            bericht._sender = reader.GetInt32(2);
            if (!reader.IsDBNull(3))
            {
                bericht._parentId = reader.GetInt32(3);
            }
            bericht._tekst = reader.GetString(4);
            if (reader.GetBoolean(5))
            {
                bericht._isVerwijderd = true;
                bericht._verwijderdDoor = reader.GetInt32(6);
            }
            else
            {
                bericht._isVerwijderd = false;
            }

            // Bericht teruggeven
            return bericht;
        }

        /// <summary>
        /// Geeft het Bericht-object op met de opgegeven Id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static Bericht FromId(int id)
        {
            // Query en parameters
            string query = "SELECT " + Select + " FROM [message] WHERE [messid] = @messid AND [removed] = 0";
            SqlParameter[] parameters = new SqlParameter[] 
            {
                new SqlParameter("messid", id)
            };

            // Reader aanmaken met deze query
            SqlDataReader reader = Provider.Instance.ExecuteReader(query, parameters);

            // Bericht maken vanuit deze reader
            Bericht bericht = null;
            if (reader.Read())
            {
                bericht = FromReader(reader);
            }

            // Reader sluiten
            reader.Close();

            // en retourneren
            return bericht;
        }

        /// <summary>
        /// Geeft het Bericht-object op met de opgegeven Id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static List<Bericht> GetAll()
        {
            // Query en parameters
            string query = "SELECT * FROM [message]";



            List<Bericht> retVal;

            // Reader aanmaken met deze query
            using (SqlDataReader reader = Provider.Instance.ExecuteReader(query))
            {
                retVal = new List<Bericht>();

                // Bericht maken vanuit deze reader
                Bericht bericht = null;
                if (reader.Read())
                {
                    bericht = FromReader(reader);
                    retVal.Add(bericht);
                }

                // Reader sluiten
                reader.Close();
            }

            // en retourneren
            return retVal;
        }
        public Profiel Eigenaar
        {
            get
            {
                return Profiel.FromId(_sender);
            }
        }

        /// <summary>
        /// Verwijderen bericht
        /// </summary>
        /// <param name="profiel"></param>
        public void Verwijder(Profiel profiel)
        {
            // query verwijderen opbouwen
            string query = "UPDATE [message] set [removed]=1, [removedby]=@removedby WHERE [messid] = @id";
            SqlParameter[] parameters = new SqlParameter[] 
            {
                new SqlParameter("removedby", profiel.Id),
                new SqlParameter("id", _id)
            };
            // update query uitvoeren
            Provider.Instance.Execute(query, parameters);
            // object bijwerken
            _isVerwijderd = true;
            _verwijderdDoor = profiel.Id;
        }

        public Profiel VerwijderdDoor
        {
            get
            {
                if (_isVerwijderd)
                {
                    return Profiel.FromId(_verwijderdDoor);
                }
                else
                {
                    return null;
                }
            }
        }

        /// <summary>
        /// Ophalen reacties bij een bericht
        /// </summary>
        public List<Bericht> Reacties
        {
            get
            {
                // Query en parameters:
                string query = "SELECT " + Select + " FROM [message] WHERE [parentmessid] = @id AND [removed] = 0";
                SqlParameter[] parameters = new SqlParameter[] 
                {
                    new SqlParameter("@id", _id)
                };
                // Reader aanmaken met deze query:
                SqlDataReader reader = Provider.Instance.ExecuteReader(query, parameters);

                // Bericht maken vanuit deze reader
                List<Bericht> reacties = new List<Bericht>();

                while (reader.Read())
                {
                    Bericht bericht = FromReader(reader);
                    reacties.Add(bericht);

                }

                // Reader sluiten
                reader.Close();

                return reacties;
            }
        }

        /// <summary>
        /// Geeft het bericht waar dit bericht een reactie op is
        /// </summary>
        public Bericht ReactieOp
        {
            get
            {
                if (_parentId == null)
                {
                    // Dit bericht is geen reactie
                    return null;
                }
                else
                {
                    return FromId(_parentId ?? 0);
                }
            }
        }

        /// <summary>
        /// Reageer op dit bericht
        /// Reactie wordt niet geplaatst indien de reagerende gebruiker
        /// is geblokkeerd door de pagina-eigenaar.
        /// </summary>
        /// <param name="profiel">De reagerende gebruiker</param>
        /// <param name="tekst">De reactie</param>
        /// <returns>Het reactie-bericht, null indien geblokkeerd door pagina-eigenaar</returns>
        public Bericht Reageer(Profiel profiel, string tekst)
        {
            if (profiel.IsGeblokkeerdDoor(HoofdBericht.Eigenaar))
            {
                return null;
            }
            else
            {
                return new Bericht(profiel, this, tekst);
            }
        }

        /// <summary>
        /// Geeft het bovenste bericht in een reactie-boom
        /// </summary>
        public Bericht HoofdBericht
        {
            get
            {
                Bericht result = this;
                // Ga telkens een bericht omhoog, totdat je niet verder kan
                do
                {
                    Bericht reactieOp = result.ReactieOp;
                    if (reactieOp == null)
                    {
                        return result;
                    }
                    else
                    {
                        result = reactieOp;
                    }
                } while (true);
            }
        }

    }
}
